package rexsee.fileSelector;

import java.io.File;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;

import rexsee.core.browser.Browser;
import rexsee.core.browser.RexseeUrl;
import rexsee.core.browser.clazz.JavascriptInterface;
import rexsee.core.lang.RexseeLanguage;
import rexsee.core.style.RexseeDrawable;
import rexsee.core.style.StyleSheet;
import rexsee.core.utilities.Json;
import rexsee.core.utilities.Utilities;
import rexsee.core.widget.DivDialog;
import rexsee.dialog.SingleLinePromptDialog;
import rexsee.dialog.SingleLinePromptDialog.SingleLinePromptDialogCallback;
import rexsee.natives.ViewStyle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class RexseeFolderSelector implements JavascriptInterface {

	public static final String INTERFACE_NAME = "FolderSelector";
	@Override
	public String getInterfaceName() {
		return mBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return this;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return new RexseeFolderSelector(childBrowser);
	}

	private final String DIALOG_STYLE = "border-width:0;vertical-spacing:1;horizontal-line:#444444;icon-width:48;icon-height:48;icon-padding:4;label-padding:4;white-space:normal;color:#FFFFFF;text-align:left;font-size:12px;background-color:black;";
	private final static String ITEM_STYLE = "icon-width:32;icon-height:32;text-align:left;background-color:#000000;color:white;label-width:fillparent;label-height:wrapcontent;label-weight:1;label-padding:4;white-space:normal;font-size:16;font-weight:bold;";

	public static final String EVENT_ONFOLDERSELECTED = "onFolderSelected";

	protected final Context mContext;
	protected final Browser mBrowser;
	private boolean syncTag = false;

	private String[] mExtensions = null;
	public String mFileIcon = "";
	public String mFolderIcon = "";
	public HashMap<String, String> mIcons = null;
	public String mCurrentPath = null;

	public FolderSelector mSelector = null;

	protected String getRoot() {
		return Environment.getExternalStorageDirectory().getAbsolutePath();
	}
	protected String getStart() {
		return Environment.getExternalStorageDirectory().getAbsolutePath();
	}
	protected boolean isValidPath(String path) {
		return true;
	}
	protected boolean isHiddenPath(String path) {
		return false;
	}

	public RexseeFolderSelector(Browser browser) {
		super();
		mBrowser = browser;
		mContext = browser.getContext();
		mBrowser.eventList.add(EVENT_ONFOLDERSELECTED);
	}

	public boolean isValidFile(String filename) {
		return (mExtensions == null) ? false : FileSelectorItem.isWithExtension(mExtensions, filename);
	}

	//JavaScript Interface 
	public void start() {
		start("");
	}
	public void start(String style) {
		start(mCurrentPath, style);
	}
	public void start(final String path, final String style) {
		start(path, style, new Runnable() {
			@Override
			public void run() {
				mBrowser.eventList.run(EVENT_ONFOLDERSELECTED);
			}
		});
	}
	public void start(final String path, final String style, final Runnable selectedRunnable) {
		dismiss();
		syncTag = false;
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					mSelector = new FolderSelector(mBrowser, style, selectedRunnable);
					mSelector.start();
					load(path);
				} catch (Exception e) {
					mBrowser.exception(getInterfaceName(), e);
				}
				syncTag = true;
			}
		});
		while (!syncTag) {
			try {
				Thread.sleep(100);
			} catch (Exception e) {

			}
		}
		return;
	}
	public void dismiss() {
		if (mSelector != null) {
			mSelector.dismiss();
			mSelector = null;
		}
	}
	public void setStyle(String style) {
		if (mSelector != null) {
			mSelector.setStyle(style);
		}
	}
	public String getStyle(String name) {
		if (mSelector != null) {
			return mSelector.getStyle(name);
		} else return "";
	}
	public boolean isStarted() {
		return mSelector != null && mSelector.isShowing();
	}

	public String getSelection() {
		return mCurrentPath;
	}
	public void load(String spath) {
		final String root = getRoot();
		final String path = (spath == null || spath.trim().equals("")) ? "file://" + getStart() : spath;
		if (!path.startsWith("file://" + root) || !isValidPath(path)) {
			mBrowser.exception(getInterfaceName(), "Invalid path.");
			return;
		}
		if (mSelector != null) {
			((Activity) mContext).runOnUiThread(new Runnable() {
				@Override
				public void run() {
					File file = new File(Uri.parse(path).getSchemeSpecificPart());
					if (file == null || !file.isDirectory() || !file.canRead()) return;
					String aPath = file.getAbsolutePath();
					mCurrentPath = "file://" + aPath;
					mSelector.adapter.load("file://" + aPath);
					mSelector.adapter.notifyDataSetChanged();
					mSelector.setTitle();
					if (aPath.equals(root) || !isValidPath(file.getParent())) {
						mSelector.parentLayout.setVisibility(View.GONE);
					} else {
						mSelector.parentLayout.setVisibility(View.VISIBLE);
					}
					if (isHiddenPath(aPath)) {
						mSelector.title.setVisibility(View.GONE);
					} else {
						mSelector.title.setVisibility(View.VISIBLE);
					}
				}
			});
		}
	}

	public void setExtensions(String extensions) {
		mExtensions = (extensions == null || extensions.trim().equals("")) ? null : extensions.trim().toLowerCase().split(",");
	}
	public String getExtensions() {
		return Json.toJson(mExtensions);
	}
	public void setFileIcons(String fileIcon, String folderIcon, String extensionIcons) {
		mFileIcon = fileIcon;
		mFolderIcon = folderIcon;
		mIcons = Utilities.string2map(extensionIcons);
	}
	public String getFileIcons() {
		String rtn = "\"folder\":\"" + mFolderIcon + "\"";
		rtn += ",\"file\":\"" + mFileIcon + "\"";
		rtn += ",\"extension\":" + Json.toJson(mIcons);
		return "{" + rtn + "}";
	}

	public void setFolderIcon(String folderIcon) {
		mFolderIcon = folderIcon;
	}
	public String getFolderIcon() {
		return mFolderIcon;
	}

	public class FolderSelector extends DivDialog {

		private TextView title;
		public LinearLayout parentLayout;
		public final ListView listView;
		public final FolderAdapter adapter;

		public FolderSelector(Browser parentBrowser, String style, final Runnable selectedRunnable) {

			super(parentBrowser, "FolderListSelector", DIALOG_STYLE + style);
			listView = new ListView(mContext);
			listView.setBackgroundColor(Color.BLACK);
			listView.setOnItemClickListener(new OnItemClickListener() {
				@Override
				public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
					File file = adapter.fileList.get(position);
					if (file == null) return;
					String path = "file://" + file.getAbsolutePath();
					if (file.isDirectory()) {
						load(path);
					} else {
					}
				}
			});
			listView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT, 1));
			Drawable divider = RexseeDrawable.getDrawable(parentBrowser, styleSheet.horizontal_line);
			if (divider != null) {
				listView.setDivider(divider);
				listView.setDividerHeight(styleSheet.getVerticalSpacing());
			}
			adapter = new FolderAdapter(mBrowser, RexseeFolderSelector.this);
			listView.setAdapter(adapter);

			title = new TextView(mContext);
			ViewStyle.setTextViewStyle(parentBrowser, title, styleSheet);
			title.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
			LinearLayout layout = new LinearLayout(mContext);
			layout.setOrientation(LinearLayout.VERTICAL);
			layout.setBackgroundColor(Color.TRANSPARENT);
			layout.addView(title);

			parentLayout = new LinearLayout(mContext);
			parentLayout.setBackgroundColor(Color.BLACK);
			parentLayout.setOrientation(LinearLayout.HORIZONTAL);
			parentLayout.setGravity(Gravity.CENTER_VERTICAL);
			ImageView parentIcon = new ImageView(mContext);
			ViewStyle.setImageViewStyle(mBrowser, parentIcon, styleSheet);
			parentIcon.setLayoutParams(styleSheet.getIconLayoutParams());
			parentIcon.setImageDrawable(adapter.folderIcon);
			parentLayout.addView(parentIcon);
			TextView parentName = new TextView(mContext);
			StyleSheet itemStyle = new StyleSheet(mContext).parseStyle(ITEM_STYLE);
			ViewStyle.setTextViewStyle(mBrowser, parentName, itemStyle);
			parentName.setLayoutParams(itemStyle.getLabelLayoutParams());
			parentName.setText("..");
			parentLayout.addView(parentName);
			parentLayout.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					File file = new File(Uri.parse(mCurrentPath).getSchemeSpecificPart());
					String parentPath = "file://" + file.getParentFile().getAbsolutePath();
					load(parentPath);
				}
			});
			parentLayout.setVisibility(View.GONE);

			layout.addView(parentLayout);
			layout.addView(listView);

			Button newFolder = new Button(mContext);
			newFolder.setText(RexseeLanguage.ACTION_NEWFOLDER);
			newFolder.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					String message = RexseeLanguage.MESSAGE_NEW_FOLDER_NAME;
					new SingleLinePromptDialog(mContext, mBrowser.application.icon, mBrowser.application.label, message, "", new SingleLinePromptDialogCallback() {
						@Override
						public void run(String input) {
							if (input == null || input.trim().equals("")) return;
							File file = new File(Uri.parse(mCurrentPath + "/" + input).getPath());
							file.mkdirs();
							mSelector.adapter.load(mCurrentPath);
							mSelector.adapter.notifyDataSetChanged();
						}
					});
				}
			});
			Button buttonConfirm = new Button(mContext);
			buttonConfirm.setText(mContext.getResources().getString(android.R.string.ok));
			buttonConfirm.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					if (selectedRunnable != null) selectedRunnable.run();
					dismiss();
				}
			});
			Button buttonCancel = new Button(mContext);
			buttonCancel.setText(mContext.getResources().getString(android.R.string.cancel));
			buttonCancel.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					dismiss();
				}
			});

			LinearLayout buttonLayout = new LinearLayout(mContext);
			buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
			buttonLayout.setBackgroundColor(Color.TRANSPARENT);
			int buttonHeight = (int) (mBrowser.application.screenDensity * 40);
			buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, buttonHeight));
			buttonLayout.addView(buttonCancel, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT, 1));
			buttonLayout.addView(newFolder, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT, 1));
			buttonLayout.addView(buttonConfirm, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT, 1));

			layout.addView(buttonLayout);

			this.addChild(layout);

		}
		public void reload() {
			((Activity) mBrowser.getContext()).runOnUiThread(new Runnable() {
				@Override
				public void run() {
					adapter.notifyDataSetChanged();
					setTitle();
				}
			});
		}
		public void setTitle() {
			title.setText(mCurrentPath);
		}

		@Override
		public boolean onKeyDown(int keyCode, KeyEvent event) {
			if (keyCode == KeyEvent.KEYCODE_BACK) {
				if (mBrowser.menu.isOptionsMenuOpen) {
					((Activity) mContext).closeOptionsMenu();
					return true;
				} else {
					if (styleSheet.window_cancelable.equalsIgnoreCase("true")) dismiss();
				}
			} else if (keyCode == KeyEvent.KEYCODE_MENU) {
				((Activity) mContext).openOptionsMenu();
			} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
				return true;
			} else if (keyCode == KeyEvent.KEYCODE_FOCUS) {
			} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
			} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
			} else {
			}
			return false;
		}

	}

	public static class FolderAdapter extends BaseAdapter {

		public final Browser mBrowser;
		private final RexseeFolderSelector mSelector;
		public final Drawable folderIcon;
		private final Drawable fileIcon;
		public final ArrayList<File> fileList = new ArrayList<File>();

		public FolderAdapter(Browser browser, RexseeFolderSelector selector) {
			mBrowser = browser;
			mSelector = selector;
			folderIcon = RexseeDrawable.getDrawable(mBrowser, mSelector.mFolderIcon, null);
			fileIcon = RexseeDrawable.getDrawable(mBrowser, mSelector.mFileIcon, null);
		}

		public void load(String url) {

			fileList.clear();
			if (url.startsWith(RexseeUrl.ASSET_URL)) return;
			File file = new File(Uri.parse(url).getSchemeSpecificPart());
			if (!file.exists()) return;
			if (!file.isDirectory()) return;
			if (!file.canRead()) return;

			String path = file.getAbsolutePath();
			String[] list = file.list();
			Arrays.sort(list, Collator.getInstance(Locale.CHINA));
			for (int i = 0; i < list.length; i++) {
				File child = new File(path + "/" + list[i]);
				if (child.isDirectory()) fileList.add(child);
			}

			for (int i = 0; i < list.length; i++) {
				File child = new File(path + "/" + list[i]);
				if (child.isFile() && mSelector.isValidFile(list[i])) fileList.add(child);
			}

		}

		@Override
		public View getView(final int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = new FileSelectorItem(mBrowser, mSelector.mSelector.styleSheet);
			}
			File file = fileList.get(position);
			Drawable iconDrawable = (file.isDirectory()) ? folderIcon : FileSelectorItem.getFileIcon(mBrowser, mSelector.mIcons, fileIcon, "file://" + file.getAbsolutePath());
			StyleSheet itemStyle = new StyleSheet(mBrowser.getContext()).parseStyle(ITEM_STYLE);
			((FileSelectorItem) convertView).set(iconDrawable, file.getName(), itemStyle, false);
			return convertView;
		}
		@Override
		public int getCount() {
			return fileList.size();
		}
		@Override
		public Object getItem(int position) {
			return position;
		}
		@Override
		public long getItemId(int position) {
			return position;
		}

		public void destroy() {
			if (folderIcon != null && folderIcon instanceof BitmapDrawable) {
				Bitmap bitmap = ((BitmapDrawable) folderIcon).getBitmap();
				if (bitmap != null && !bitmap.isRecycled()) bitmap.recycle();
			}
			if (fileIcon != null && fileIcon instanceof BitmapDrawable) {
				Bitmap bitmap = ((BitmapDrawable) fileIcon).getBitmap();
				if (bitmap != null && !bitmap.isRecycled()) bitmap.recycle();
			}
		}

	}

}
